[UPDATE] MediaPackage v2がHarvest Jobsをサポートしました![Live-to-VOD]
はじめに
清水です。AWS Elemental MediaPackage v2でHarvest Jobがサポートされました!2024/10/31時点ではまだAWS What's Newへのポストはありませんが、AWS Elemental MediaPackage v2 User GuideのDocument historyに2024/10/30付けでサポートされた旨が記載されています。
引用元: Document history for the MediaPackage User Guide - AWS Elemental MediaPackage
ライブストリームからVODアセットを作成するHarvest Job、MediaPackage v1でサポートされたのは2019年10月のことでしたね。(もう5年前です!)
2021年5月にはDASHエンドポイントからのVOD作成もサポートしていました。
このLive-to-VOD機能、個人的にその機能もさることならが Harvest Job という名称も好きで、MediaPackage v2で使えるようになるのを今か今かと待ちわびていました。その名にふさわしい時期にサポートしてくれましたね!本エントリでは実際にMediaPackage v2でHarvest Jobをやってみたのでまとめてみたいと思います。
MediaPackge v2でHarvest Jobするためのリソースについて
MediaPackage v2 User guideの以下ページを参考にしながら、実際にHarvest Jobをやってみます。
Harvest Jobの実行にはStartover windowを設定し、Harvest Jobの対象となる時間内でいわゆるタイムシフト再生が可能な状態である必要があります。この点はMediaPackage v1のHarvest Jobと変わりありませんね。
AWSマネジメントコンソールからOrigin endpointを作成した場合、デフォルトで900秒(15分)のStartover windowが設定されていますが、今回は以下ブログエントリでタイムシフト再生をした環境を利用することにしました。MediaLiveとMediaPackageリソースで構成されています。
MediaPackageまわりの設定を振り返っておくと、ChannelのInput typeはCMAF
(CMAF ingestを利用してMediaLiveと連携)、Origin endpointのContainer typeはCMAF
、Startover windowは3600
(60分)というぐあいです。またEndpoint policyはAttach a public policy
を選択しています。(こちらについては、のちほど詳細を確認します。)
ライブストリームの実施についても、上記ブログエントリと同様の環境で検証を行いました。
MediaPackage v2でHarvest Jobをするためのアクセス権限の確認
続いて、MediaPackage v2でHarvest Jobを実施するために必要なアクセス権限まわりを確認します。こちらもUser guideの該当ページを参考に進めます。
主に2つにアクセス権限まわりを確認します。1つ目はMediaPackage v2のendpointに対して与えるHarvestObject
権限です。そして2つ目は、Harvest Jobの出力先となるS3バケットのアクセス権限です。こちらはMediaPackage v2のservice pricinpalにPutObject
の権限を付与する必要があります。それぞれ実際にみていきましょう。
Origin endpointに対するHarvestObject権限の付与
MediaPackage v2ではEgressを保護するEndpoint policyがあります。
動画再生時のManifestやSegmentのURLを保護するかたちですね。Harvest JobではOrigin endpointからコンテンツを収集します。そのため、このEgress保護のEndpoint policyでHarvestJobの処理に対する許可を与える必要があるわけです。
この設定例についてはUser Guide内、以下ページ記載があります。
冒頭の MediaPackage L2V Harvester の項目ですね。抜粋すると以下のようになります。
{
"Version": "2012-10-17",
"Id": "MediaPackageHarvesterAccessPolicy",
"Statement": [
{
{
"Sid": "AllowMediaPackageHarvestObjectAccess",
"Effect": "Allow",
"Principal": {
"Service": "mediapackagev2.amazonaws.com"
},
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "AccountID"
}
},
"Action": [
"mediapackagev2:HarvestObject",
"mediapackagev2:GetObject"
],
"Resource": "arn:aws:mediapackagev2:Region:AccountID:channelGroup/ChannelGroupName/channel/ChannelName/originEndpoint/OriginEndpointName
}
}
]
}
このポリシーをOrigin endpointに設定するわけですが、先のエントリで作成した(2024/10/31の時点で作成した)Origin endpointのPolicyを確認してみると、以下のように設定されていました。(なお、Attach a public policy
で作成したものです。)
{
"Version" : "2012-10-17",
"Statement" : [ {
"Sid" : "AllowPublicGetObjectAccess",
"Effect" : "Allow",
"Principal" : "*",
"Action" : [ "mediapackagev2:GetHeadObject", "mediapackagev2:GetObject" ],
"Resource" : "arn:aws:mediapackagev2:ap-northeast-1:123456789012:channelGroup/mediapackage-v2-channel-group/channel/time-shifted-viewing-channel/originEndpoint/time-shifted-viewing-origin-endpoint"
}, {
"Sid" : "AllowMediaPackageHarvestObjectAccess",
"Effect" : "Allow",
"Principal" : {
"Service" : "mediapackagev2.amazonaws.com"
},
"Action" : "mediapackagev2:HarvestObject",
"Resource" : "arn:aws:mediapackagev2:ap-northeast-1:123456789012:channelGroup/mediapackage-v2-channel-group/channel/time-shifted-viewing-channel/originEndpoint/time-shifted-viewing-origin-endpoint",
"Condition" : {
"StringEquals" : {
"AWS:SourceAccount" : "123456789012"
}
}
} ]
}
改めてCreate origin endpointページのEndpoint policyの項目、Attach a public policy
に設定した場合のPolicyを確認してみます。下のほうにAllowMediaPackageHarvestObjectAccess
として追加されていますね。
ただし、以前Attach a public policy
で作成したOrigin endpointに自動で権限が追加されている、ということは ありませんでした。 あらたにEndpointを作成する場合は、Attach a public policy
の場合には権限を追加する必要はありませんが、これまでに作成済みのEndpointを使用する場合は権限を追加する必要がある点に注意しましょう。
Harvest Jobの出力先S3バケットに対するPutObject権限の付与
上記のEndpoint policyに加えて、Harvest Jobの出力先となるS3バケットに対してPutObjectの権限も必要です。User GuideにはMediaPackage v2 service principal権限を与えるよう記載されていますね。
実はこちらの権限、具体的な内容がUser Guideに記載されていなかったことから、設定せずにHarvest Jobを実施(作成)しようとしてみたのですが、以下のエラーが発生してしまいました。
Harvest job create operation failed
ValidationException: Validation error encountered at request.s3DestinationConfig: Unable to write to S3 destination bucket. Verify MediaPackageV2 service principal mediapackagev2.amazonaws.com is allow listed write access to the bucket and the bucket region is in the same region.
このメッセージ、つまりMediaPackageV2 service principalとしてmediapackagev2.amazonaws.com
に権限を与えよ、ということをヒントに出力先S3バケットのバケットポリシーを設定します。ELB(ALB)のアクセスログ設定を参考にしてみました。
「Step 2: Attach a policy to your S3 bucket」の「Regions available as of August 2022 or later」に対するポリシーを参考にします。以下の内容ですね。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "logdelivery.elasticloadbalancing.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "s3-bucket-arn"
}
]
}
ここで、"Service": "logdelivery.elasticloadbalancing.amazonaws.com"
の箇所を"Service": "mediapackagev2.amazonaws.com"
に置き換えます。また"Resource": "s3-bucket-arn"
は"Resource": "arn:aws:s3:::content-source-xxxxxxxx/*"
というように、実際のS3バケット名と許可対象のパスに置き換えました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid" : "AllowMediaPackageHarvestJobPutObject",
"Effect": "Allow",
"Principal": {
"Service": "mediapackagev2.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::content-source-xxxxxxxx/*"
}
]
}
ただし、これだけだとAWSアカウント関係なく、Harvest Jobを行うMediaPackage v2リソースに許可が与えられてしまうのでは?と考え(実際にそうなってしまうかは未確認ではありますが)、先ほどのEndpoint policyを参考に以下のように"AWS:SourceAccount"
の条件を加えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid" : "AllowMediaPackageHarvestJobPutObject",
"Effect": "Allow",
"Principal": {
"Service": "mediapackagev2.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::content-source-xxxxxxxx/*",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "123456789012"
}
}
}
]
}
今回Harvest Jobの出力先に使用するS3バケットcontent-source-xxxxxxxx
ですが、実際には別の検証で利用したものを流用したことなどから、PublicReadの権限が付与されています。そのため、最終的には以下のBucket policyを設定するかたちとなりました。
{
"Version": "2012-10-17",
"Id": "PublicReadForGetBucketObjects",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::content-source-xxxxxxxx/*"
},
{
"Sid": "AllowMediaPackageHarvestJobPutObject",
"Effect": "Allow",
"Principal": {
"Service": "mediapackagev2.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::content-source-xxxxxxxx/*",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "123456789012"
}
}
}
]
}
MediaPackage v2でHarvest Jobをやってみた
それでは実際にMediaPackage v2でHarvest Jobを作成してみます。対象のMediaPackage v2のChannelリソース詳細画面、Harvest Jobsの項目に進みます。(Newマークがついていますね!)[Create harvest job]ボタンを押下します。
Harvest job nameとDescriptionを適切に設定します。Cannel group nameとChannel nameは変更ができないようでした。選択されているものをそのまま利用します。Origin endpoint nameで対象とするendpointを選択します。またHarvest manifests nameでこちらも対象とするmanifest definitionsを選択します。
Schedule configurationでStart date and timeならびにEnd date and timeを入力します。Destinationでは、出力先となるS3バケットを選択、pathについても入力しておきます。
[Create harvest job]ボタンでHarvest Jobを作成しましょう。In progress
のStatusでJobの作成に成功しました。
Harvest Jobの詳細画面は以下のようなぐあいです。
今回は体感ですが2,3分もかからないうちにJobがCompleted
となりました。
出力先となるS3バケットを確認してみます。直下にdestination pathとして指定したemp-v2-harvest-job
という(便宜上の)フォルダが作成され、その中に収穫物が格納されていますね。
先ほど述べたとおり、このS3バケットは別検証で利用したものを流用しており、Public Access可能にしているほかCORSについても設定してみます。hls.js demoのページでManifestファイルのURLを入力、再生を確認してみました。
Harvest jobで作成したVODコンテンツが再生できました!
Harvest jobで作成されたManifestファイルを確認
無事にMediaPackage v2のHarvest JobでVODアセットが作成できました。このVODアセットのManifestファイルについても確認してみます。S3内のManifestファイルのURLにcurlコマンドでアクセスしました。
% curl https://content-source-xxxxxxxx.s3.ap-northeast-1.amazonaws.com/emp-v2-harvest-job/index.m3u8
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:LANGUAGE="und",AUTOSELECT=YES,CHANNELS="2",TYPE=AUDIO,URI="variant_audio_aac.m3u8",GROUP-ID="audio_0",DEFAULT=NO,NAME="und"
#EXT-X-STREAM-INF:CODECS="mp4a.40.2,avc1.640028",AVERAGE-BANDWIDTH=5000000,RESOLUTION=1920x1080,VIDEO-RANGE=SDR,FRAME-RATE=29.97,BANDWIDTH=5000000,AUDIO="audio_0"
variant_video_1080p30.m3u8
#EXT-X-STREAM-INF:CODECS="mp4a.40.2,avc1.64001F",AVERAGE-BANDWIDTH=3000000,RESOLUTION=1280x720,VIDEO-RANGE=SDR,FRAME-RATE=29.97,BANDWIDTH=3000000,AUDIO="audio_0"
variant_video_720p30.m3u8
% curl https://content-source-xxxxxxxx.s3.ap-northeast-1.amazonaws.com/emp-v2-harvest-job/variant_video_1080p30.m3u8
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:288106095
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-MAP:URI="segment_video_1080p30_288104887_init.mp4"
#EXTINF:6.006,
segment_video_1080p30_288106095.mp4
#EXTINF:6.006,
segment_video_1080p30_288106096.mp4
#EXTINF:6.006,
segment_video_1080p30_288106097.mp4
#EXTINF:6.006,
segment_video_1080p30_288106098.mp4
#EXTINF:6.006,
segment_video_1080p30_288106099.mp4
#EXTINF:6.006,
segment_video_1080p30_288106100.mp4
#EXTINF:6.006,
segment_video_1080p30_288106101.mp4
#EXTINF:6.006,
segment_video_1080p30_288106102.mp4
#EXTINF:6.006,
segment_video_1080p30_288106103.mp4
#EXTINF:6.006,
segment_video_1080p30_288106104.mp4
#EXTINF:6.006,
segment_video_1080p30_288106105.mp4
#EXTINF:6.006,
segment_video_1080p30_288106106.mp4
#EXTINF:6.006,
segment_video_1080p30_288106107.mp4
#EXTINF:6.006,
segment_video_1080p30_288106108.mp4
#EXTINF:6.006,
segment_video_1080p30_288106109.mp4
#EXTINF:6.006,
segment_video_1080p30_288106110.mp4
#EXTINF:6.006,
segment_video_1080p30_288106111.mp4
#EXTINF:6.006,
segment_video_1080p30_288106112.mp4
#EXTINF:6.006,
segment_video_1080p30_288106113.mp4
#EXTINF:6.006,
segment_video_1080p30_288106114.mp4
#EXTINF:6.006,
segment_video_1080p30_288106115.mp4
#EXTINF:6.006,
segment_video_1080p30_288106116.mp4
#EXTINF:6.006,
segment_video_1080p30_288106117.mp4
#EXTINF:6.006,
segment_video_1080p30_288106118.mp4
#EXTINF:6.006,
segment_video_1080p30_288106119.mp4
#EXTINF:6.006,
segment_video_1080p30_288106120.mp4
#EXTINF:6.006,
segment_video_1080p30_288106121.mp4
#EXTINF:6.006,
segment_video_1080p30_288106122.mp4
#EXTINF:6.006,
segment_video_1080p30_288106123.mp4
#EXTINF:6.006,
segment_video_1080p30_288106124.mp4
#EXTINF:6.006,
segment_video_1080p30_288106125.mp4
#EXTINF:6.006,
segment_video_1080p30_288106126.mp4
#EXTINF:6.006,
segment_video_1080p30_288106127.mp4
#EXTINF:6.006,
segment_video_1080p30_288106128.mp4
#EXTINF:6.006,
segment_video_1080p30_288106129.mp4
#EXTINF:6.006,
segment_video_1080p30_288106130.mp4
#EXTINF:6.006,
segment_video_1080p30_288106131.mp4
#EXTINF:6.006,
segment_video_1080p30_288106132.mp4
#EXTINF:6.006,
segment_video_1080p30_288106133.mp4
#EXTINF:6.006,
segment_video_1080p30_288106134.mp4
#EXTINF:6.006,
segment_video_1080p30_288106135.mp4
#EXTINF:6.006,
segment_video_1080p30_288106136.mp4
#EXTINF:6.006,
segment_video_1080p30_288106137.mp4
#EXTINF:6.006,
segment_video_1080p30_288106138.mp4
#EXTINF:6.006,
segment_video_1080p30_288106139.mp4
#EXTINF:6.006,
segment_video_1080p30_288106140.mp4
#EXTINF:6.006,
segment_video_1080p30_288106141.mp4
#EXTINF:6.006,
segment_video_1080p30_288106142.mp4
#EXTINF:6.006,
segment_video_1080p30_288106143.mp4
#EXTINF:6.006,
segment_video_1080p30_288106144.mp4
#EXT-X-ENDLIST
Harvest Jobの指定時間はStart time (local)が2024/10/31 18:00:00 (UTC+09:00)、End time (local)が2024/10/31 18:05:00 (UTC+09:00)でした。同じ時間帯にMediaPackage v2でタイムシフト再生した際のManifestファイルについても確認してみましょう。同様の内容となっていることが確認できますね。(ぱっとみた限りですが、Child manifestは同じ内容、ManifestファイルのURIが少し異なるぐらいでしょうか。)
% curl "https://xxxxxx.egress.xxxxxx.mediapackagev2.ap-northeast-1.amazonaws.com/out/v1/mediapackage-v2-channel-group/time-shifted-viewing-channel/time-shifted-viewing-origin-endpoint/index.m3u8?start=2024-10-31T09:00:00Z&end=2024-10-31T09:05:00Z"
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:LANGUAGE="und",AUTOSELECT=YES,CHANNELS="2",TYPE=AUDIO,URI="variant_audio_aac.m3u8?start=2024-10-31T09:00:00Z&end=2024-10-31T09:05:00Z",GROUP-ID="audio_0",DEFAULT=NO,NAME="und"
#EXT-X-STREAM-INF:CODECS="mp4a.40.2,avc1.640028",AVERAGE-BANDWIDTH=5000000,RESOLUTION=1920x1080,VIDEO-RANGE=SDR,FRAME-RATE=29.97,BANDWIDTH=5000000,AUDIO="audio_0"
variant_video_1080p30.m3u8?start=2024-10-31T09:00:00Z&end=2024-10-31T09:05:00Z
#EXT-X-STREAM-INF:CODECS="mp4a.40.2,avc1.64001F",AVERAGE-BANDWIDTH=3000000,RESOLUTION=1280x720,VIDEO-RANGE=SDR,FRAME-RATE=29.97,BANDWIDTH=3000000,AUDIO="audio_0"
variant_video_720p30.m3u8?start=2024-10-31T09:00:00Z&end=2024-10-31T09:05:00Z
% curl "https://xxxxxx.egress.xxxxxx.mediapackagev2.ap-northeast-1.amazonaws.com/out/v1/mediapackage-v2-channel-group/time-shifted-viewing-channel/time-shifted-viewing-origin-endpoint/variant_video_1080p30.m3u8?start=2024-10-31T09:00:00Z&end=2024-10-31T09:05:00Z"
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:288106095
#EXT-X-DISCONTINUITY-SEQUENCE:0
#EXT-X-MAP:URI="segment_video_1080p30_288104887_init.mp4"
#EXTINF:6.006,
segment_video_1080p30_288106095.mp4
#EXTINF:6.006,
segment_video_1080p30_288106096.mp4
#EXTINF:6.006,
segment_video_1080p30_288106097.mp4
#EXTINF:6.006,
segment_video_1080p30_288106098.mp4
#EXTINF:6.006,
segment_video_1080p30_288106099.mp4
#EXTINF:6.006,
segment_video_1080p30_288106100.mp4
#EXTINF:6.006,
segment_video_1080p30_288106101.mp4
#EXTINF:6.006,
segment_video_1080p30_288106102.mp4
#EXTINF:6.006,
segment_video_1080p30_288106103.mp4
#EXTINF:6.006,
segment_video_1080p30_288106104.mp4
#EXTINF:6.006,
segment_video_1080p30_288106105.mp4
#EXTINF:6.006,
segment_video_1080p30_288106106.mp4
#EXTINF:6.006,
segment_video_1080p30_288106107.mp4
#EXTINF:6.006,
segment_video_1080p30_288106108.mp4
#EXTINF:6.006,
segment_video_1080p30_288106109.mp4
#EXTINF:6.006,
segment_video_1080p30_288106110.mp4
#EXTINF:6.006,
segment_video_1080p30_288106111.mp4
#EXTINF:6.006,
segment_video_1080p30_288106112.mp4
#EXTINF:6.006,
segment_video_1080p30_288106113.mp4
#EXTINF:6.006,
segment_video_1080p30_288106114.mp4
#EXTINF:6.006,
segment_video_1080p30_288106115.mp4
#EXTINF:6.006,
segment_video_1080p30_288106116.mp4
#EXTINF:6.006,
segment_video_1080p30_288106117.mp4
#EXTINF:6.006,
segment_video_1080p30_288106118.mp4
#EXTINF:6.006,
segment_video_1080p30_288106119.mp4
#EXTINF:6.006,
segment_video_1080p30_288106120.mp4
#EXTINF:6.006,
segment_video_1080p30_288106121.mp4
#EXTINF:6.006,
segment_video_1080p30_288106122.mp4
#EXTINF:6.006,
segment_video_1080p30_288106123.mp4
#EXTINF:6.006,
segment_video_1080p30_288106124.mp4
#EXTINF:6.006,
segment_video_1080p30_288106125.mp4
#EXTINF:6.006,
segment_video_1080p30_288106126.mp4
#EXTINF:6.006,
segment_video_1080p30_288106127.mp4
#EXTINF:6.006,
segment_video_1080p30_288106128.mp4
#EXTINF:6.006,
segment_video_1080p30_288106129.mp4
#EXTINF:6.006,
segment_video_1080p30_288106130.mp4
#EXTINF:6.006,
segment_video_1080p30_288106131.mp4
#EXTINF:6.006,
segment_video_1080p30_288106132.mp4
#EXTINF:6.006,
segment_video_1080p30_288106133.mp4
#EXTINF:6.006,
segment_video_1080p30_288106134.mp4
#EXTINF:6.006,
segment_video_1080p30_288106135.mp4
#EXTINF:6.006,
segment_video_1080p30_288106136.mp4
#EXTINF:6.006,
segment_video_1080p30_288106137.mp4
#EXTINF:6.006,
segment_video_1080p30_288106138.mp4
#EXTINF:6.006,
segment_video_1080p30_288106139.mp4
#EXTINF:6.006,
segment_video_1080p30_288106140.mp4
#EXTINF:6.006,
segment_video_1080p30_288106141.mp4
#EXTINF:6.006,
segment_video_1080p30_288106142.mp4
#EXTINF:6.006,
segment_video_1080p30_288106143.mp4
#EXTINF:6.006,
segment_video_1080p30_288106144.mp4
#EXT-X-ENDLIST
まとめ
AWS Elemental MediaPackage v2で新たにサポートしたHarvest Jobsについて、実際にライブストリームからVODアセットを作成して動作を確認してみました。
MediaPackageのEndponit側でタイムシフト再生が可能になっている必要があるなど、基本的にはMediaPackage v1と同様の操作感かと思います。ただし、権限まわりの設定については異なります。見返してみるとMediaPackage v1のころはS3バケットへの書き込み権限を設定したIAMロールを作成し、Harvest Job作成の際にそのIAMロールを指定するかたちでした。
MediaPackage v2ではPolicyまわりがよりAWSらしく強化されています。そのため、MediaPackage v2のHarvest Jobでも、Endpoint policyでアクセス許可を設定します。また出力先となるS3バケット側ではBucket policyでアクセス許可を行いました。このアクセス権限、ポリシーまわりがv1と異なることに注意しながら、MediaPackage v2でもHarvest Jobを活用していきましょう!